/***************************************************************************************************
  *Copyright(C),2010-2017,Sumscope
  *FileName	:  TinyString.h
  *Author	:  scofined.qi
  *Version	:  1.0
  *Date		:  2020/06/12
  *Desc		:  //用于主要说明此程序文件完成的主要功能
  *Relation :  
  *Others	:  //其他内容说明
  *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
  *History	:  //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
***************************************************************************************************/
#pragma once

#include <string.h>
#include <string>
#include "../core.h"
namespace qb{
	namespace base{
		/*
			与KeyString的异同:
			KeyString在指针指向一块字符串的时候,额外分配了1到2个字节,用于
			在字符串前面存储字符串的长度
			TinyString则没有,直接指针指向字符串,如果需要长度,则需要strlen来计算

			为什么要这么做?
			部分场景下,原先键为std::string,那么通常有std::string作为参数的
			获取接口,如果以KeyString为键,那么每次查找都必须多一次
			从std::string到KeyString的转化,导致多一次内存分配
			为了避免这个多余的内存分配,必须移除长度编码
			然后配合TempTinyString来搭配使用
		*/
        class S_CORE_EXPORT TinyString{
			typedef TinyString ThisType;
		public:
			enum : uint64_t {
				MostBitFlag = (sizeof(uintptr_t) == 4 ? 0x80000000 : 0x8000000000000000LL),
				LowBitMask = 0x7F,			// 首个字符的第七位掩码
				TinyLength = 1 << 7,		// 短字符串长度,超过此值需要用2个字符存储长度
				MaxLength = (1 << 15) - 1	// 最大字符串长度,长于此值截断
			};
		protected:
			union{
				const char*	m_data;			// 0结尾的指针,最高位为1,获取真实指针需要移除
				char		m_raw[4];		// 存储不超过3个字符的短字符串,依旧是0结尾
			};
		public:
			~TinyString();
			TinyString();
			TinyString(const char* str);
			TinyString(const char* str, int len);
			TinyString(const std::string& str);
			TinyString(const ThisType& str);
			TinyString(ThisType&& str);
			TinyString& operator=(ThisType&& str);
			TinyString& operator=(ThisType& str);
			TinyString& operator=(const char* str);
			TinyString& operator+=(const ThisType& str);
			TinyString& operator+=(const char* str);
			inline const char* c_str()const{
				return ptr_impl();
			}

			inline void Reset(){
				destroy();
			}
			inline int size()const{
				return strlen(ptr_impl());
			}
			int bytes()const;
			inline bool empty()const{ return size() <= 0; }
			operator const char*()const{ return c_str(); }
			bool operator<(const ThisType& str)const
			{
				return scompare(c_str(), size(), str.c_str(), str.size()) < 0;
			}
			bool operator<(const char* str)const
			{
				return scompare(c_str(), size(), str, str ? strlen(str) : 0) < 0;
			}
			bool operator>(const char* str)const
			{
				return scompare(c_str(), size(), str, str ? strlen(str) : 0) > 0;
			}
			bool operator>(const ThisType& str)const
			{
				return scompare(c_str(), size(), str.c_str(), str.size())>0;
			}
			inline bool operator==(const ThisType& str)const{
				return strcmp(ptr_impl(), str.ptr_impl()) == 0;
			}
			inline bool operator==(const char* str)const{
				return strcmp(str ? str : blank(), ptr_impl()) == 0;
			}
			bool assign_plus(const char* str, int len, const char* post, int postLen);
			bool assign(const char* str, int len);
		protected:
			static inline int scompare(const char* self, int slen, const char* str, int len)
			{
				if (slen <= 0 && len <= 0)return 0;
				else if (slen <= 0)return -1;
				else if (len <= 0)return 1;
				return strcmp(self, str);
			}
			inline bool istiny() const
			{
				return m_data != nullptr && !haspointer();
			}
			inline void destroy()
			{
				if (!istiny() && m_data)
					delete[] pointer();
				m_data = nullptr;
			}
			inline bool haspointer()const
			{
				return ((uintptr_t)m_data & MostBitFlag)!=0;
			}
			inline const char* pointer()const{
				return (const char*)((uintptr_t)m_data & ~MostBitFlag);
			}
			inline void set_pointer(const char* ptr){
				m_data = (const char*)((uintptr_t)ptr | MostBitFlag);
			}
			inline void set_length(char* data, int total)const
			{
			}
		protected:
			// 始终获取字符串指针,如果为null返回空指针,使得上层无需关心null指针
			inline const char* ptr_impl()const{
				return m_data == nullptr ? blank() : (
					((uintptr_t)m_data & MostBitFlag) ?
					(const char*)((uintptr_t)m_data & ~MostBitFlag) : m_raw
					);
			}
			inline const char* blank()const{
				static const char blank_str[4] = { 0, 0, 0, 0 };
				return blank_str;
			}
		};


		// 主要用于解决性能问题
        class TempTinyString : public TinyString{
		private:
			// 限定该类型的用途,只能在栈上临时使用,不能被new创建
			// 限定TinyString的哪几个接口为私有,不能被使用
			TempTinyString(const TempTinyString& ts) = delete;
			TempTinyString& operator=(const TempTinyString&) = delete;
			TempTinyString& operator=(const char*) = delete;
			TempTinyString& operator=(const std::string& str) = delete;
			void* operator new(size_t size) = delete;
			using TinyString::assign;
			using TinyString::assign_plus;
			using TinyString::Reset;
		public:
			TempTinyString(const std::string& str){ m_data = (const char*)(((uintptr_t)str.c_str()) | MostBitFlag); }
			TempTinyString(const char* str){ m_data = (const char*)(((uintptr_t)str) | MostBitFlag); }
			~TempTinyString(){m_data = nullptr;}
		};
	}//namespace base;
}//namespace qb;
